home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / AbstractButton.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  47.2 KB  |  1,443 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)AbstractButton.java    1.97 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package javax.swing;
  15.  
  16. import java.awt.*;
  17. import java.awt.event.*;
  18. import java.awt.image.*;
  19. import java.io.Serializable;
  20. import javax.swing.event.*;
  21. import javax.swing.border.*;
  22. import javax.swing.plaf.*;
  23. import javax.accessibility.*;
  24.  
  25. /**
  26.  * Defines the common behaviors for the JButton, JToggleButton, JCheckbox,
  27.  * and the JRadioButton classes.
  28.  * <p>
  29.  * <strong>Warning:</strong>
  30.  * Serialized objects of this class will not be compatible with 
  31.  * future Swing releases.  The current serialization support is appropriate
  32.  * for short term storage or RMI between applications running the same
  33.  * version of Swing.  A future release of Swing will provide support for
  34.  * long term persistence.
  35.  *
  36.  * @version 1.97 08/28/98
  37.  * @author Jeff Dinkins
  38.  */
  39. public abstract class AbstractButton extends JComponent implements ItemSelectable, SwingConstants {
  40.  
  41.     // *********************************
  42.     // ******* Button properties *******
  43.     // *********************************
  44.  
  45.     /** Identifies a change in the button model. */
  46.     public static final String MODEL_CHANGED_PROPERTY = "model";
  47.     /** Identifies a change in the button's text. */
  48.     public static final String TEXT_CHANGED_PROPERTY = "text";
  49.     /** Identifies a change to the button's mnemonic. */
  50.     public static final String MNEMONIC_CHANGED_PROPERTY = "mnemonic";
  51.  
  52.     // Text positioning and alignment
  53.     /** Identifies a change in the button's margins. */
  54.     public static final String MARGIN_CHANGED_PROPERTY = "margin";
  55.     /** Identifies a change in the button's vertical alignment. */
  56.     public static final String VERTICAL_ALIGNMENT_CHANGED_PROPERTY = "verticalAlignment";
  57.     /** Identifies a change in the button's horizontal alignment. */
  58.     public static final String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = "horizontalAlignment";
  59.  
  60.     /** Identifies a change in the button's vertical text position. */
  61.     public static final String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = "verticalTextPosition";
  62.     /** Identifies a change in the button's horizontal text position. */
  63.     public static final String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = "horizontalTextPosition";
  64.  
  65.     // Paint options
  66.     /** Identifies a change to having the border drawn, or having it not drawn. */
  67.     public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
  68.     /** Identifies a change to having the border highlighted when focused, or not. */
  69.     public static final String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
  70.     /** Identifies a change in the button's  */
  71.     public static final String ROLLOVER_ENABLED_CHANGED_PROPERTY = "rolloverEnabled";
  72.     /** Identifies a change from rollover enabled to disabled or back to enabled. */
  73.     public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY = "contentAreaFilled";
  74.  
  75.     // Icons
  76.     /** Identifies a change to the icon that represents the button. */
  77.     public static final String ICON_CHANGED_PROPERTY = "icon";
  78.  
  79.     /** Identifies a change to the icon used when the button has been pressed. */
  80.     public static final String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
  81.     /** Identifies a change to the icon used when the button has been selected. */
  82.     public static final String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
  83.  
  84.     /** Identifies a change to the icon used when the cursor is over the button. */
  85.     public static final String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
  86.     /** Identifies a change to the icon used when the cursror is over the button and it has been selected. */
  87.     public static final String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = "rolloverSelectedIcon";
  88.  
  89.     /** Identifies a change to the icon used when the button has been disabled. */
  90.     public static final String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
  91.     /** Identifies a change to the icon used when the button has been disabled and selected. */
  92.     public static final String DISABLED_SELECTED_ICON_CHANGED_PROPERTY = "disabledSelectedIcon";
  93.  
  94.  
  95.     /** The data model that determines the button's state. */
  96.     protected ButtonModel model                = null;  
  97.  
  98.     private String     text                    = ""; // for BeanBox
  99.     private Insets     margin                  = null;
  100.     private Insets     defaultMargin           = null;
  101.  
  102.     // Button icons
  103.     // PENDING(jeff) - hold icons in an array
  104.     private Icon       defaultIcon             = null;
  105.     private Icon       pressedIcon             = null;
  106.     private Icon       disabledIcon            = null;
  107.  
  108.     private Icon       selectedIcon            = null;
  109.     private Icon       disabledSelectedIcon    = null;
  110.  
  111.     private Icon       rolloverIcon            = null;
  112.     private Icon       rolloverSelectedIcon    = null;
  113.     
  114.     // Display properties
  115.     private boolean    paintBorder             = true;  
  116.     private boolean    paintFocus              = true;
  117.     private boolean    rolloverEnabled         = false;   
  118.     private boolean    contentAreaFilled         = true; 
  119.  
  120.     // Icon/Label Alignment
  121.     private int        verticalAlignment       = CENTER;
  122.     private int        horizontalAlignment     = CENTER;
  123.     
  124.     private int        verticalTextPosition    = CENTER;
  125.     private int        horizontalTextPosition  = RIGHT;
  126.  
  127.     /** 
  128.      * The button's model listeners.
  129.      */
  130.     protected ChangeListener changeListener = null;
  131.     protected ActionListener actionListener = null;
  132.     protected ItemListener itemListener = null;
  133.  
  134.     /**
  135.      * Only one ChangeEvent is needed per button instance since the
  136.      * event's only state is the source property.  The source of events
  137.      * generated is always "this".
  138.      */
  139.     protected transient ChangeEvent changeEvent;
  140.     
  141.     /**
  142.      * Returns the button's text.
  143.      * @see #setText
  144.      */
  145.     public String getText() {
  146.         return text;
  147.     }
  148.     
  149.     /**
  150.      * Sets the button's text.
  151.      * @param t the string used to set the text
  152.      * @see #getText
  153.      * @beaninfo
  154.      *        bound: true
  155.      *    preferred: true
  156.      *    attribute: visualUpdate true
  157.      *  description: The button's text.
  158.      */
  159.     public void setText(String text) {
  160.         String oldValue = this.text;
  161.         this.text = text;
  162.         firePropertyChange(TEXT_CHANGED_PROPERTY, oldValue, text);
  163.         if (accessibleContext != null) {
  164.             accessibleContext.firePropertyChange(
  165.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  166.                 oldValue, text);
  167.         }
  168.         if (text == null || oldValue == null || !text.equals(oldValue)) {
  169.             revalidate();
  170.             repaint();
  171.         }
  172.     }
  173.  
  174.  
  175.     /**
  176.      * Returns the state of the button. True if the
  177.      * toggle button is selected, false if it's not.
  178.      */
  179.     public boolean isSelected() {
  180.         return model.isSelected();
  181.     }
  182.  
  183.     /**
  184.      * Sets the state of the button. Note that this method does not
  185.      * trigger an actionEvent. Call doClick() to perform a programatic
  186.      * action change.
  187.      */
  188.     public void setSelected(boolean b) {
  189.         boolean oldValue = isSelected();
  190.         if (accessibleContext != null && oldValue != b) {
  191.             if (b) {
  192.                 accessibleContext.firePropertyChange(
  193.                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  194.                     null, AccessibleState.SELECTED);
  195.             } else {
  196.                 accessibleContext.firePropertyChange(
  197.                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  198.                     AccessibleState.SELECTED, null);
  199.             }
  200.         }
  201.         model.setSelected(b);
  202.     }
  203.  
  204.     /**
  205.      * Programatically perform a "click". This does the same
  206.      * thing as if the user had pressed and released the button.
  207.      */
  208.     public void doClick() {
  209.         doClick(68);
  210.     }
  211.  
  212.     /**
  213.      * Programatically perform a "click". This does the same
  214.      * thing as if the user had pressed and released the button.
  215.      * The button stays visually "pressed" for pressTime milliseconds.
  216.      */
  217.     public void doClick(int pressTime) {
  218.         Dimension size = getSize();
  219.         model.setArmed(true);
  220.         model.setPressed(true);
  221.         paintImmediately(new Rectangle(0,0, size.width, size.height));
  222.         try {
  223.             Thread.currentThread().sleep(pressTime);
  224.         } catch(InterruptedException ie) {
  225.         }
  226.         model.setPressed(false);
  227.         model.setArmed(false);
  228.     }
  229.  
  230.     /**
  231.      * Sets space for margin between the button's border and
  232.      * the label. Setting to null will cause the button to
  233.      * use the default margin.  The button's default Border
  234.      * object will use this value to create the proper margin.
  235.      * However, if a non-default border is set on the button, 
  236.      * it is that Border object's responsibility to create the
  237.      * appropriate margin space (else this property will
  238.      * effectively be ignored).
  239.      *
  240.      * @param m the space between the border and the label
  241.      *
  242.      * @beaninfo
  243.      *        bound: true
  244.      *    attribute: visualUpdate true
  245.      *  description: The space between the button's border and the label.
  246.      */
  247.     public void setMargin(Insets m) {
  248.         // Cache the old margin if it comes from the UI
  249.         if(m instanceof UIResource) {
  250.             defaultMargin = m;
  251.         } else if(margin instanceof UIResource) {
  252.             defaultMargin = margin;
  253.         }
  254.             
  255.         // If the client passes in a null insets, restore the margin
  256.         // from the UI if possible
  257.         if(m == null && defaultMargin != null) {
  258.             m = defaultMargin;
  259.         }
  260.  
  261.         Insets old = margin;
  262.         margin = m;
  263.         firePropertyChange(MARGIN_CHANGED_PROPERTY, old, m);
  264.         if (old == null || !m.equals(old)) {
  265.             revalidate();
  266.             repaint();
  267.         }
  268.     }
  269.  
  270.     /**
  271.      * Returns the margin between the button's border and
  272.      * the label.
  273.      * @see #setMargin
  274.      */
  275.     public Insets getMargin() {
  276.         return margin;
  277.     }
  278.  
  279.     /**
  280.      * Returns the default icon.
  281.      * @see #setIcon
  282.      */
  283.     public Icon getIcon() {
  284.         return defaultIcon;
  285.     }
  286.     
  287.     /**
  288.      * Sets the button's default icon. This icon is
  289.      * also used as the "pressed" and "disabled" icon if
  290.      * there is no explicitly set pressed icon.
  291.      * @param g the icon used as the default image
  292.      * @see #getIcon
  293.      * @see #setPressedIcon
  294.      * @beaninfo 
  295.      *           bound: true
  296.      *       attribute: visualUpdate true
  297.      *     description: The button's default icon
  298.      */
  299.     public void setIcon(Icon defaultIcon) {
  300.         Icon oldValue = this.defaultIcon;
  301.         this.defaultIcon = defaultIcon;
  302.         firePropertyChange(ICON_CHANGED_PROPERTY, oldValue, defaultIcon);
  303.         if (accessibleContext != null) {
  304.             accessibleContext.firePropertyChange(
  305.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  306.                 oldValue, defaultIcon);
  307.         }
  308.         if (defaultIcon != oldValue) {
  309.             if (defaultIcon == null || oldValue == null ||
  310.                 defaultIcon.getIconWidth() != oldValue.getIconWidth() ||
  311.                 defaultIcon.getIconHeight() != oldValue.getIconHeight()) {
  312.                 revalidate();
  313.             } 
  314.             repaint();
  315.         }
  316.     }
  317.     
  318.     /**
  319.      * Returns the pressed icon for the button.
  320.      * @see #setPressedIcon
  321.      */
  322.     public Icon getPressedIcon() {
  323.         return pressedIcon;
  324.     }
  325.     
  326.     /**
  327.      * Sets the pressed icon for the button.
  328.      * @param g the icon used as the "pressed" image
  329.      * @see #getPressedIcon
  330.      * @beaninfo
  331.      *        bound: true
  332.      *    attribute: visualUpdate true
  333.      *  description: The pressed icon for the button.
  334.      */
  335.     public void setPressedIcon(Icon pressedIcon) {
  336.         Icon oldValue = this.pressedIcon;
  337.         this.pressedIcon = pressedIcon;
  338.         firePropertyChange(PRESSED_ICON_CHANGED_PROPERTY, oldValue, pressedIcon);
  339.         if (accessibleContext != null) {
  340.             accessibleContext.firePropertyChange(
  341.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  342.                 oldValue, defaultIcon);
  343.         }
  344.         if (pressedIcon != oldValue) {
  345.             if (getModel().isPressed()) {
  346.                 repaint();
  347.             }
  348.         }
  349.     }
  350.  
  351.     /**
  352.      * Returns the selected icon for the button.
  353.      * @see #setSelectedIcon
  354.      */
  355.     public Icon getSelectedIcon() {
  356.         return selectedIcon;
  357.     }
  358.     
  359.     /**
  360.      * Sets the selected icon for the button.
  361.      * @param g the icon used as the "selected" image
  362.      * @see #getSelectedIcon
  363.      * @beaninfo
  364.      *        bound: true
  365.      *    attribute: visualUpdate true
  366.      *  description: The selected icon for the button.
  367.      */
  368.     public void setSelectedIcon(Icon selectedIcon) {
  369.         Icon oldValue = this.selectedIcon;
  370.         this.selectedIcon = selectedIcon;
  371.         firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, oldValue, selectedIcon);
  372.         if (accessibleContext != null) {
  373.             accessibleContext.firePropertyChange(
  374.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  375.                 oldValue, selectedIcon);
  376.         }
  377.         if (selectedIcon != oldValue) {
  378.             if (isSelected()) {
  379.                 repaint();
  380.             }
  381.         }
  382.     }
  383.  
  384.     /**
  385.      * Returns the rollover icon for the button.
  386.      * @see #setRolloverIcon
  387.      */
  388.     public Icon getRolloverIcon() {
  389.         return rolloverIcon;
  390.     }
  391.     
  392.     /**
  393.      * Sets the rollover icon for the button.
  394.      * @param g the icon used as the "rollover" image
  395.      * @see #getRolloverIcon
  396.      * @beaninfo
  397.      *        bound: true
  398.      *    attribute: visualUpdate true
  399.      *  description: The rollover icon for the button.
  400.      */
  401.     public void setRolloverIcon(Icon rolloverIcon) {
  402.         Icon oldValue = this.rolloverIcon;
  403.         this.rolloverIcon = rolloverIcon;
  404.         firePropertyChange(ROLLOVER_ICON_CHANGED_PROPERTY, oldValue, rolloverIcon);
  405.         if (accessibleContext != null) {
  406.             accessibleContext.firePropertyChange(
  407.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  408.                 oldValue, rolloverIcon);
  409.         }
  410.         setRolloverEnabled(true);
  411.         if (rolloverIcon != oldValue) {
  412.             // No way to determine whether we are currently in
  413.             // a rollover state, so repaint regardless
  414.             repaint();
  415.         }
  416.       
  417.     }
  418.     
  419.     /**
  420.      * Returns the rollover seletion icon for the button.
  421.      * @see #setRolloverSelectedIcon
  422.      */
  423.     public Icon getRolloverSelectedIcon() {
  424.         return rolloverSelectedIcon;
  425.     }
  426.     
  427.     /**
  428.      * Sets the rollover selected icon for the button.
  429.      * @param g the icon used as the "selected rollover" image
  430.      * @see #getRolloverSelectedIcon
  431.      * @beaninfo
  432.      *        bound: true
  433.      *    attribute: visualUpdate true
  434.      *  description: The rollover selected icon for the button.
  435.      */
  436.     public void setRolloverSelectedIcon(Icon rolloverSelectedIcon) {
  437.         Icon oldValue = this.rolloverSelectedIcon;
  438.         this.rolloverSelectedIcon = rolloverSelectedIcon;
  439.         firePropertyChange(ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY, oldValue, rolloverSelectedIcon);
  440.         if (accessibleContext != null) {
  441.             accessibleContext.firePropertyChange(
  442.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  443.                 oldValue, rolloverSelectedIcon);
  444.         }
  445.         if (rolloverSelectedIcon != oldValue) {
  446.             // No way to determine whether we are currently in
  447.             // a rollover state, so repaint regardless
  448.             if (isSelected()) {
  449.                 repaint();
  450.             }
  451.         }
  452.     }
  453.     
  454.     /**
  455.      * Returns the icon used by the button when it's disabled.
  456.      * If not no disabled icon has been set, the button constructs
  457.      * one from the default icon. 
  458.      * PENDING(jeff): the disabled icon really should be created 
  459.      * (if necesary) by the L&F.
  460.      * @see #getPressedIcon
  461.      * @see #setDisabledIcon
  462.      */
  463.     public Icon getDisabledIcon() {
  464.         if(disabledIcon == null) {
  465.             if(defaultIcon != null
  466.                && defaultIcon instanceof ImageIcon) {
  467.                 disabledIcon = new ImageIcon(
  468.                     GrayFilter.createDisabledImage(
  469.                         ((ImageIcon)defaultIcon).getImage()));
  470.             }
  471.         }
  472.         return disabledIcon;
  473.     }
  474.     
  475.     /**
  476.      * Sets the disabled icon for the button.
  477.      * @param g the icon used as the disabled image
  478.      * @see #getDisabledIcon
  479.      * @beaninfo
  480.      *        bound: true
  481.      *    attribute: visualUpdate true
  482.      *  description: The disabled icon for the button.
  483.      */
  484.     public void setDisabledIcon(Icon disabledIcon) {
  485.         Icon oldValue = this.disabledIcon;
  486.         this.disabledIcon = disabledIcon;
  487.         firePropertyChange(DISABLED_ICON_CHANGED_PROPERTY, oldValue, disabledIcon);
  488.         if (accessibleContext != null) {
  489.             accessibleContext.firePropertyChange(
  490.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  491.                 oldValue, disabledIcon);
  492.         }
  493.         if (disabledIcon != oldValue) {
  494.             if (!isEnabled()) {
  495.                 repaint();
  496.             }
  497.         }
  498.     }
  499.     
  500.     /**
  501.      * Returns the icon used by the button when it's disabled and selected.
  502.      * If not no disabled selection icon has been set, the button constructs
  503.      * one from the selection icon. 
  504.      * PENDING(jeff): the disabled selection icon really should be created 
  505.      * (if necesary) by the L&F.
  506.      * @see #getPressedIcon
  507.      * @see #setDisabledIcon
  508.      */
  509.     public Icon getDisabledSelectedIcon() {
  510.         if(disabledSelectedIcon == null) {
  511.             if(selectedIcon != null && selectedIcon instanceof ImageIcon) {
  512.                 disabledSelectedIcon = new ImageIcon(
  513.                     GrayFilter.createDisabledImage(((ImageIcon)selectedIcon).getImage()));
  514.             } else {
  515.                 return disabledIcon;
  516.             }
  517.         }
  518.         return disabledSelectedIcon;
  519.     }
  520.  
  521.     /**
  522.      * Sets the disabled selection icon for the button.
  523.      * @param g the icon used as the disabled selection image
  524.      * @see #getDisabledSelectedIcon
  525.      */
  526.     public void setDisabledSelectedIcon(Icon disabledSelectedIcon) {
  527.         Icon oldValue = this.disabledSelectedIcon;
  528.         this.disabledSelectedIcon = disabledSelectedIcon;
  529.         firePropertyChange(DISABLED_SELECTED_ICON_CHANGED_PROPERTY, oldValue, disabledSelectedIcon);
  530.         if (accessibleContext != null) {
  531.             accessibleContext.firePropertyChange(
  532.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  533.                 oldValue, disabledSelectedIcon);
  534.         }
  535.         if (disabledSelectedIcon != oldValue) {
  536.             if (disabledSelectedIcon == null || oldValue == null ||
  537.                 disabledSelectedIcon.getIconWidth() != oldValue.getIconWidth() ||
  538.                 disabledSelectedIcon.getIconHeight() != oldValue.getIconHeight()) {
  539.                 revalidate();
  540.             } 
  541.             if (!isEnabled() && isSelected()) {
  542.                 repaint();
  543.             }
  544.         }
  545.     }
  546.  
  547.     /**
  548.      * Returns the vertical alignment of the text and icon.
  549.      * Valid keys: CENTER (the default), TOP, BOTTOM
  550.      */
  551.     public int getVerticalAlignment() {
  552.         return verticalAlignment;
  553.     }
  554.     
  555.     /**
  556.      * Sets the vertical alignment of the icon and text.
  557.      * Valid keys: CENTER (the default), TOP, BOTTOM
  558.      * @beaninfo
  559.      *        bound: true
  560.      *         enum: TOP    SwingConstants.TOP
  561.      *               CENTER SwingConstants.CENTER
  562.      *               BOTTOM  SwingConstants.BOTTOM
  563.      *    attribute: visualUpdate true
  564.      *  description: The vertical alignment of the icon and text.
  565.      */
  566.     public void setVerticalAlignment(int alignment) {
  567.         if (alignment == verticalAlignment) return;
  568.         int oldValue = verticalAlignment;
  569.         verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
  570.         firePropertyChange(VERTICAL_ALIGNMENT_CHANGED_PROPERTY, oldValue, verticalAlignment);         repaint();
  571.     }
  572.     
  573.     /**
  574.      * Returns the horizontal alignment of the icon and text.
  575.      * Valid keys: CENTER (the default), LEFT, RIGHT
  576.      */
  577.     public int getHorizontalAlignment() {
  578.         return horizontalAlignment;
  579.     }
  580.     
  581.     /**
  582.      * Sets the horizontal alignment of the icon and text.
  583.      * Valid keys: CENTER (the default), LEFT, RIGHT, LEADING or TRAILING
  584.      * @beaninfo
  585.      *        bound: true
  586.      *         enum: LEFT     SwingConstants.LEFT
  587.      *               CENTER   SwingConstants.CENTER
  588.      *               RIGHT    SwingConstants.RIGHT
  589.      *               LEADING  SwingConstants.LEADING
  590.      *               TRAILING SwingConstants.TRAILING
  591.      *    attribute: visualUpdate true
  592.      *  description: The horizontal alignment of the icon and text.
  593.      */
  594.     public void setHorizontalAlignment(int alignment) {
  595.         if (alignment == horizontalAlignment) return;
  596.         int oldValue = horizontalAlignment;
  597.         horizontalAlignment = checkHorizontalKey(alignment,
  598.                                                  "horizontalAlignment");
  599.         firePropertyChange(HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY,
  600.                            oldValue, horizontalAlignment);       
  601.         repaint();
  602.     }
  603.  
  604.     
  605.     /**
  606.      * Returns the vertical position of the text relative to the icon
  607.      * Valid keys: CENTER (the default), TOP, BOTTOM
  608.      */
  609.     public int getVerticalTextPosition() {
  610.         return verticalTextPosition;
  611.     }
  612.     
  613.     /**
  614.      * Sets the vertical position of the text relative to the icon.
  615.      * Valid keys: CENTER (the default), TOP, BOTTOM
  616.      * @beaninfo
  617.      *        bound: true
  618.      *         enum: TOP    SwingConstants.TOP
  619.      *               CENTER SwingConstants.CENTER
  620.      *               BOTTOM SwingConstants.BOTTOM
  621.      *    attribute: visualUpdate true
  622.      *  description: The vertical position of the text relative to the icon.
  623.      */
  624.     public void setVerticalTextPosition(int textPosition) {
  625.         if (textPosition == verticalTextPosition) return;
  626.         int oldValue = verticalTextPosition;
  627.         verticalTextPosition = checkVerticalKey(textPosition, "verticalTextPosition");
  628.         firePropertyChange(VERTICAL_TEXT_POSITION_CHANGED_PROPERTY, oldValue, verticalTextPosition);
  629.         repaint();
  630.     }
  631.     
  632.     /**
  633.      * Sets the horizontal position of the text relative to the icon.
  634.      * Valid keys: RIGHT (the default), LEFT, CENTER
  635.      */
  636.     public int getHorizontalTextPosition() {
  637.         return horizontalTextPosition;
  638.     }
  639.     
  640.     /**
  641.      * Sets the horizontal position of the text relative to the icon.
  642.      * Valid keys: RIGHT (the default), LEFT, CENTER, LEADING, TRAILING
  643.      * @exception IllegalArgumentException
  644.      * @beaninfo
  645.      *        bound: true
  646.      *         enum: LEFT     SwingConstants.LEFT
  647.      *               CENTER   SwingConstants.CENTER
  648.      *               RIGHT    SwingConstants.RIGHT
  649.      *               LEADING  SwingConstants.LEADING
  650.      *               TRAILING SwingConstants.TRAILING
  651.      *    attribute: visualUpdate true
  652.      *  description: The horizontal position of the text relative to the icon.
  653.      */
  654.     public void setHorizontalTextPosition(int textPosition) {
  655.         if (textPosition == horizontalTextPosition) return;
  656.         int oldValue = horizontalTextPosition;
  657.         horizontalTextPosition = checkHorizontalKey(textPosition,
  658.                                                     "horizontalTextPosition");
  659.         firePropertyChange(HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY,
  660.                            oldValue,
  661.                            horizontalTextPosition);
  662.         repaint();
  663.     }
  664.     
  665.     /**
  666.      * Verify that key is a legal value for the horizontalAlignment properties.
  667.      *
  668.      * @param key the property value to check
  669.      * @param exception the IllegalArgumentException detail message 
  670.      * @exception IllegalArgumentException if key isn't LEFT, CENTER, RIGHT,
  671.      * LEADING or TRAILING.
  672.      * @see #setHorizontalTextPosition
  673.      * @see #setHorizontalAlignment
  674.      */
  675.     protected int checkHorizontalKey(int key, String exception) {
  676.         if ((key == LEFT) ||
  677.             (key == CENTER) ||
  678.             (key == RIGHT) ||
  679.             (key == LEADING) ||
  680.             (key == TRAILING)) {
  681.             return key;
  682.         } else {
  683.             throw new IllegalArgumentException(exception);
  684.         }
  685.     }
  686.     
  687.     /**
  688.      * Ensures that the key is a valid. Throws an IllegalArgument exception
  689.      * exception otherwise.
  690.      */
  691.     protected int checkVerticalKey(int key, String exception) {
  692.         if ((key == TOP) || (key == CENTER) || (key == BOTTOM)) {
  693.             return key;
  694.         } else {
  695.             throw new IllegalArgumentException(exception);
  696.         }
  697.     }
  698.     
  699.     /**
  700.      * Sets the action command for this button. 
  701.      */
  702.     public void setActionCommand(String actionCommand) {
  703.         getModel().setActionCommand(actionCommand);
  704.     }
  705.     
  706.     /**
  707.      * Returns the action command for this button. 
  708.      */
  709.     public String getActionCommand() {
  710.         String ac = getModel().getActionCommand();
  711.         if(ac == null) {
  712.             ac = getText();
  713.         }
  714.         return ac;
  715.     }
  716.     
  717.     /**
  718.      * Returns whether the border should be painted.
  719.      * @see #setBorderPainted
  720.      */
  721.     public boolean isBorderPainted() {
  722.         return paintBorder;
  723.     }
  724.     
  725.     /**
  726.      * Sets whether the border should be painted.
  727.      * @param b if true and border property is not null, the border is painted.
  728.      * @see #isBorderPainted
  729.      * @beaninfo
  730.      *        bound: true
  731.      *    attribute: visualUpdate true
  732.      *  description: Whether the border should be painted.
  733.      */
  734.     public void setBorderPainted(boolean b) {
  735.         boolean oldValue = paintBorder;
  736.         paintBorder = b;
  737.         firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, oldValue, paintBorder);
  738.         if (b != oldValue) {
  739.             revalidate();
  740.             repaint();
  741.         }
  742.     }
  743.  
  744.     /**
  745.      * Paint the button's border if BorderPainted property is true.
  746.      * 
  747.      * @see #paint
  748.      * @see #setBorder
  749.      */
  750.     protected void paintBorder(Graphics g) {    
  751.         if (isBorderPainted()) {
  752.             super.paintBorder(g);
  753.         }
  754.     }
  755.  
  756.     /**
  757.      * Returns whether focus should be painted.
  758.      * @see #setFocusPainted
  759.      */
  760.     public boolean isFocusPainted() {
  761.         return paintFocus;
  762.     }
  763.     
  764.     /**
  765.      * Sets whether focus should be painted.
  766.      * @param b if true, the focus state is painted.
  767.      * @see #isFocusPainted
  768.      * @beaninfo
  769.      *        bound: true
  770.      *    attribute: visualUpdate true
  771.      *  description: Whether focus should be painted
  772.      */
  773.     public void setFocusPainted(boolean b) {
  774.         boolean oldValue = paintFocus;
  775.         paintFocus = b;
  776.         firePropertyChange(FOCUS_PAINTED_CHANGED_PROPERTY, oldValue, paintFocus);
  777.         if (b != oldValue && hasFocus()) {
  778.             revalidate();
  779.             repaint();
  780.         }
  781.     }
  782.  
  783.     /**
  784.      * Checks whether the "content area" of the button should be filled.
  785.      * @see #setFocusPainted
  786.      */
  787.     public boolean isContentAreaFilled() {
  788.         return contentAreaFilled;
  789.     }
  790.     
  791.     /**
  792.      * Sets whether the button should paint the content area
  793.      * or leave it transparent.  If you wish to have a transparent
  794.      * button, for example and icon only button, then you should set
  795.      * this to false.  Do not call setOpaque(false).  Whether the button
  796.      * follows the RepaintManager's concept of opacity is L&F depandant.
  797.      *
  798.      * This function may cause the component's opaque property to change.
  799.      *
  800.      * The exact behavior of calling this function varies on a
  801.      * component-by-component and L&F-by-L&F basis.
  802.      *
  803.      * @param b if true, rollover effects should be painted.
  804.      * @see #isContentAreaFilled
  805.      * @see #setOpaque
  806.      * @beaninfo
  807.      *        bound: true
  808.      *    attribute: visualUpdate true
  809.      *  description: Whether the button should paint the content area
  810.      *               or leave it transparent.
  811.      */
  812.     public void setContentAreaFilled(boolean b) {
  813.         boolean oldValue = contentAreaFilled;
  814.         contentAreaFilled = b;
  815.         firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, oldValue, contentAreaFilled);
  816.         if (b != oldValue) {
  817.             repaint();
  818.         }
  819.     }
  820.  
  821.     /**
  822.      * Checks whether rollover effects are enabled.
  823.      * @see #setFocusPainted
  824.      */
  825.     public boolean isRolloverEnabled() {
  826.         return rolloverEnabled;
  827.     }
  828.     
  829.     /**
  830.      * Sets whether rollover effects should be enabled.
  831.      * @param b if true, rollover effects should be painted.
  832.      * @see #isRolloverEnabled
  833.      * @beaninfo
  834.      *        bound: true
  835.      *    attribute: visualUpdate true
  836.      *  description: Whether rollover effects should be enabled.
  837.      */
  838.     public void setRolloverEnabled(boolean b) {
  839.         boolean oldValue = rolloverEnabled;
  840.         rolloverEnabled = b;
  841.         firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, oldValue, rolloverEnabled);
  842.         if (b != oldValue) {
  843.             repaint();
  844.         }
  845.     }
  846.  
  847.     /**
  848.      * Get the keyboard mnemonic from the the current model 
  849.      */
  850.     public int getMnemonic() {
  851.         return model.getMnemonic();
  852.     }
  853.  
  854.     /**
  855.      * Set the keyboard mnemonic on the current model.
  856.      *
  857.      * @param mnemonic the key code which represents the mnemonic
  858.      * @beaninfo
  859.      *        bound: true
  860.      *    attribute: visualUpdate true
  861.      *  description: the keyboard character mnemonic
  862.      */
  863.     public void setMnemonic(int mnemonic) {
  864.         int oldValue = getMnemonic();
  865.         model.setMnemonic(mnemonic);
  866.         firePropertyChange(MNEMONIC_CHANGED_PROPERTY, oldValue, mnemonic);
  867.         if (mnemonic != oldValue) {
  868.             revalidate();
  869.             repaint();
  870.         }
  871.     }
  872.  
  873.     /**
  874.      * Specifies the mnemonic value.
  875.      *
  876.      * @param mnemonic  a char specifying the mnemonic value
  877.      */
  878.     public void setMnemonic(char mnemonic) {
  879.         int vk = (int) mnemonic;
  880.         if(vk >= 'a' && vk <='z')
  881.             vk -= ('a' - 'A');
  882.         setMnemonic(vk);
  883.     }
  884.  
  885.     /**
  886.      * Get the model that this button represents.
  887.      * @see #setModel
  888.      */
  889.     public ButtonModel getModel() {
  890.         return model;
  891.     }
  892.     
  893.     /**
  894.      * Set the model that this button represents.
  895.      * @param m the Model
  896.      * @see #getModel
  897.      * @beaninfo
  898.      *        bound: true
  899.      *  description: Model that the Button uses.
  900.      */
  901.     public void setModel(ButtonModel newModel) {
  902.         
  903.         ButtonModel oldModel = getModel();
  904.         
  905.         if (oldModel != null) {
  906.             oldModel.removeChangeListener(changeListener);
  907.             oldModel.removeActionListener(actionListener);
  908.             changeListener = null;
  909.             actionListener = null;
  910.         }
  911.         
  912.         model = newModel;
  913.         
  914.         if (newModel != null) {
  915.             changeListener = createChangeListener();
  916.             actionListener = createActionListener();
  917.             itemListener = createItemListener();
  918.             newModel.addChangeListener(changeListener);
  919.             newModel.addActionListener(actionListener);
  920.             newModel.addItemListener(itemListener);
  921.         }
  922.  
  923.         firePropertyChange(MODEL_CHANGED_PROPERTY, oldModel, newModel);
  924.         if (newModel != oldModel) {
  925.             revalidate();
  926.             repaint();
  927.         }
  928.     }
  929.  
  930.     
  931.     /**
  932.      * Returns the button's current UI.
  933.      * @see #setUI
  934.      */
  935.     public ButtonUI getUI() {
  936.         return (ButtonUI) ui;
  937.     }
  938.  
  939.     
  940.     /**
  941.      * Sets the button's UI.
  942.      * @param ui the new ButtonUI
  943.      * @see #getUI
  944.      */
  945.     public void setUI(ButtonUI ui) {
  946.         super.setUI(ui);
  947.     }
  948.  
  949.     
  950.     /**
  951.      * Gets a new UI object from the default UIFactory. Subtypes of
  952.      * AbstractButton should override this to update the UI. For
  953.      * example, JButton might do the following:
  954.      *      setUI((ButtonUI)UIManager.getUI(
  955.      *          "ButtonUI", "javax.swing.plaf.basic.BasicButtonUI", this));
  956.      */
  957.     public void updateUI() {
  958.     }
  959.     
  960.     /**
  961.      * Adds a ChangeListener to the button.
  962.      */
  963.     public void addChangeListener(ChangeListener l) {
  964.         listenerList.add(ChangeListener.class, l);
  965.     }
  966.     
  967.     /**
  968.      * Removes a ChangeListener from the button.
  969.      */
  970.     public void removeChangeListener(ChangeListener l) {
  971.         listenerList.remove(ChangeListener.class, l);
  972.     }
  973.     
  974.     /*
  975.      * Notify all listeners that have registered interest for
  976.      * notification on this event type.  The event instance 
  977.      * is lazily created using the parameters passed into 
  978.      * the fire method.
  979.      * @see EventListenerList
  980.      */
  981.     protected void fireStateChanged() {
  982.         // Guaranteed to return a non-null array
  983.         Object[] listeners = listenerList.getListenerList();
  984.         // Process the listeners last to first, notifying
  985.         // those that are interested in this event
  986.         for (int i = listeners.length-2; i>=0; i-=2) {
  987.             if (listeners[i]==ChangeListener.class) {
  988.                 // Lazily create the event:
  989.                 if (changeEvent == null)
  990.                     changeEvent = new ChangeEvent(this);
  991.                 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  992.             }          
  993.         }
  994.     }   
  995.  
  996.     /**
  997.      * adds an ActionListener to the button
  998.      */
  999.     public void addActionListener(ActionListener l) {
  1000.         listenerList.add(ActionListener.class, l);
  1001.     }
  1002.     
  1003.     /**
  1004.      * removes an ActionListener from the button
  1005.      */
  1006.     public void removeActionListener(ActionListener l) {
  1007.         listenerList.remove(ActionListener.class, l);
  1008.     }
  1009.     
  1010.     
  1011.     /**
  1012.      * Subclasses that want to handle ChangeEvents differently
  1013.      * can override this to return another ChangeListener implementation.
  1014.      */
  1015.     protected ChangeListener createChangeListener() {
  1016.         return (ChangeListener) new ButtonChangeListener();
  1017.     }
  1018.  
  1019.     /**
  1020.      * Extend ChangeListener to be serializable
  1021.      * <p>
  1022.      * <strong>Warning:</strong>
  1023.      * Serialized objects of this class will not be compatible with
  1024.      * future Swing releases.  The current serialization support is appropriate
  1025.      * for short term storage or RMI between applications running the same
  1026.      * version of Swing.  A future release of Swing will provide support for
  1027.      * long term persistence.
  1028.      */
  1029.     protected class ButtonChangeListener implements ChangeListener, Serializable {
  1030.         ButtonChangeListener() {
  1031.         }
  1032.  
  1033.         public void stateChanged(ChangeEvent e) {
  1034.             fireStateChanged();
  1035.             repaint();
  1036.         }
  1037.     }
  1038.  
  1039.  
  1040.     /*
  1041.      * Notify all listeners that have registered interest for
  1042.      * notification on this event type.  The event instance 
  1043.      * is lazily created using the parameters passed into 
  1044.      * the fire method.
  1045.      * @see EventListenerList
  1046.      */
  1047.     protected void fireActionPerformed(ActionEvent event) {
  1048.         // Guaranteed to return a non-null array
  1049.         Object[] listeners = listenerList.getListenerList();
  1050.         ActionEvent e = null;
  1051.         // Process the listeners last to first, notifying
  1052.         // those that are interested in this event
  1053.         for (int i = listeners.length-2; i>=0; i-=2) {
  1054.             if (listeners[i]==ActionListener.class) {
  1055.                 // Lazily create the event:
  1056.                 if (e == null) {
  1057.                       String actionCommand = event.getActionCommand();
  1058.                       if(actionCommand == null) {
  1059.                          actionCommand = getActionCommand();
  1060.                       }
  1061.                       e = new ActionEvent(AbstractButton.this,
  1062.                                           ActionEvent.ACTION_PERFORMED,
  1063.                                           actionCommand,
  1064.                                           event.getModifiers());
  1065.                 }
  1066.                 ((ActionListener)listeners[i+1]).actionPerformed(e);
  1067.             }          
  1068.         }
  1069.     }
  1070.     
  1071.     /*
  1072.      * Notify all listeners that have registered interest for
  1073.      * notification on this event type.  The event instance 
  1074.      * is lazily created using the parameters passed into 
  1075.      * the fire method.
  1076.      * @see EventListenerList
  1077.      */
  1078.     protected void fireItemStateChanged(ItemEvent event) {
  1079.         // Guaranteed to return a non-null array
  1080.         Object[] listeners = listenerList.getListenerList();
  1081.         ItemEvent e = null;
  1082.         // Process the listeners last to first, notifying
  1083.         // those that are interested in this event
  1084.         for (int i = listeners.length-2; i>=0; i-=2) {
  1085.             if (listeners[i]==ItemListener.class) {
  1086.                 // Lazily create the event:
  1087.                 if (e == null) {
  1088.                     e = new ItemEvent(AbstractButton.this,
  1089.                                       ItemEvent.ITEM_STATE_CHANGED,
  1090.                                       AbstractButton.this,
  1091.                                       event.getStateChange());
  1092.                 }
  1093.                 ((ItemListener)listeners[i+1]).itemStateChanged(e);
  1094.             }          
  1095.         }
  1096.     }
  1097.     
  1098.  
  1099.     private class ForwardActionEvents implements ActionListener, Serializable {
  1100.         public void actionPerformed(ActionEvent event) {
  1101.             fireActionPerformed(event);
  1102.         }
  1103.     }
  1104.  
  1105.     protected ActionListener createActionListener() {
  1106.         return new ForwardActionEvents();
  1107.     }
  1108.  
  1109.  
  1110.     private class ForwardItemEvents implements ItemListener, Serializable {
  1111.         public void itemStateChanged(ItemEvent event) {
  1112.             fireItemStateChanged(event);
  1113.         }
  1114.     }
  1115.  
  1116.     protected ItemListener createItemListener() {
  1117.         return new ForwardItemEvents();
  1118.     }
  1119.  
  1120.     
  1121.     /**
  1122.      * Enables (or disables) the button.
  1123.      */
  1124.     public void setEnabled(boolean b) {
  1125.         super.setEnabled(b);
  1126.         model.setEnabled(b);
  1127.     }
  1128.  
  1129.     // *** Deprecated java.awt.Button APIs below *** //
  1130.     
  1131.     /**
  1132.      * Returns the label text.
  1133.      *
  1134.      * @return a String containing the label
  1135.      * @deprecated - Replaced by getText()
  1136.      */
  1137.     public String getLabel() {
  1138.         return getText();
  1139.     }
  1140.     
  1141.     /**
  1142.      * Sets the label text.
  1143.      *
  1144.      * @param label  a String containing the text
  1145.      * @deprecated - Replaced by setText(text)
  1146.      * @beaninfo
  1147.      *        bound: true
  1148.      *  description: Replace by setText(text)
  1149.      */
  1150.     public void setLabel(String label) {
  1151.         setText(label);
  1152.     }
  1153.  
  1154.     /**
  1155.      * adds an ItemListener to the checkbox
  1156.      */
  1157.     public void addItemListener(ItemListener l) {
  1158.         listenerList.add(ItemListener.class, l);
  1159.     }
  1160.     
  1161.     /**
  1162.      * removes an ItemListener from the button
  1163.      */
  1164.     public void removeItemListener(ItemListener l) {
  1165.         listenerList.remove(ItemListener.class, l);
  1166.     }
  1167.  
  1168.    /**
  1169.      * Returns an array (length 1) containing the label or null if the 
  1170.      * button is not selected.
  1171.      *
  1172.      * @return an array containing 1 Object -- the text of the button
  1173.      *         -- if the item is selected, otherwise null
  1174.      */
  1175.     public synchronized Object[] getSelectedObjects() {
  1176.         if (isSelected() == false) {
  1177.             return null;
  1178.         }
  1179.         Object[] selectedObjects = new Object[1];
  1180.         selectedObjects[0] = getText();
  1181.         return selectedObjects;
  1182.     }
  1183.  
  1184.     protected void init(String text, Icon icon) {
  1185.         setLayout(new OverlayLayout(this));
  1186.  
  1187.         if(text != null) {
  1188.             setText(text);
  1189.         }
  1190.         
  1191.         if(icon != null) {
  1192.             setIcon(icon);
  1193.         }
  1194.         
  1195.         // Set the UI
  1196.         updateUI();
  1197.         
  1198.         // Listen for Focus events
  1199.         addFocusListener(
  1200.             new FocusListener() {
  1201.             public void focusGained(FocusEvent event) {
  1202.                 if (accessibleContext != null) {
  1203.                     accessibleContext.firePropertyChange(
  1204.                         AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1205.                         null, AccessibleState.FOCUSED);
  1206.                 }
  1207.             }
  1208.             public void focusLost(FocusEvent event) {
  1209.                 if (accessibleContext != null) {
  1210.                     accessibleContext.firePropertyChange(
  1211.                         AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1212.                         null, AccessibleState.FOCUSED);
  1213.                 }
  1214.                 // repaint focus is lost
  1215.                 if(isFocusPainted()) {
  1216.                     repaint();
  1217.                 }
  1218.             }
  1219.         }
  1220.         );
  1221.  
  1222.         setAlignmentX(LEFT_ALIGNMENT);
  1223.     }
  1224.  
  1225.  
  1226.     /**
  1227.      * Returns a string representation of this AbstractButton. This method 
  1228.      * is intended to be used only for debugging purposes, and the 
  1229.      * content and format of the returned string may vary between      
  1230.      * implementations. The returned string may be empty but may not 
  1231.      * be <code>null</code>.
  1232.      * <P>
  1233.      * Overriding paramString() to provide information about the
  1234.      * specific new aspects of the JFC components.
  1235.      * 
  1236.      * @return  a string representation of this AbstractButton.
  1237.      */
  1238.     protected String paramString() {
  1239.     String defaultIconString = (defaultIcon != null ?
  1240.                     defaultIcon.toString() : "");
  1241.     String pressedIconString = (pressedIcon != null ?
  1242.                     pressedIcon.toString() : "");
  1243.     String disabledIconString = (disabledIcon != null ?
  1244.                      disabledIcon.toString() : "");
  1245.     String selectedIconString = (selectedIcon != null ?
  1246.                      selectedIcon.toString() : "");
  1247.     String disabledSelectedIconString = (disabledSelectedIcon != null ?
  1248.                          disabledSelectedIcon.toString()
  1249.                          : "");
  1250.     String rolloverIconString = (rolloverIcon != null ?
  1251.                      rolloverIcon.toString() : "");
  1252.     String rolloverSelectedIconString = (rolloverSelectedIcon != null ?
  1253.                          rolloverSelectedIcon.toString()
  1254.                          : "");
  1255.     String paintBorderString = (paintBorder ? "true" : "false");
  1256.     String paintFocusString = (paintFocus ? "true" : "false");
  1257.     String rolloverEnabledString = (rolloverEnabled ? "true" : "false");
  1258.  
  1259.     return super.paramString() +
  1260.     ",defaultIcon=" + defaultIconString +
  1261.     ",disabledIcon=" + disabledIconString +
  1262.     ",disabledSelectedIcon=" + disabledSelectedIconString +
  1263.     ",margin=" + margin +
  1264.     ",paintBorder=" + paintBorderString +
  1265.     ",paintFocus=" + paintFocusString +
  1266.     ",pressedIcon=" + pressedIconString +
  1267.     ",rolloverEnabled=" + rolloverEnabledString +
  1268.     ",rolloverIcon=" + rolloverIconString +
  1269.     ",rolloverSelectedIcon=" + rolloverSelectedIconString +
  1270.     ",selectedIcon=" + selectedIconString +
  1271.     ",text=" + text;
  1272.     }
  1273.  
  1274.  
  1275. ///////////////////
  1276. // Accessibility support
  1277. ///////////////////
  1278.     /**
  1279.      * Accessiblity support.
  1280.      * <p>
  1281.      * <strong>Warning:</strong>
  1282.      * Serialized objects of this class will not be compatible with
  1283.      * future Swing releases.  The current serialization support is appropriate
  1284.      * for short term storage or RMI between applications running the same
  1285.      * version of Swing.  A future release of Swing will provide support for
  1286.      * long term persistence.
  1287.      */
  1288.     protected abstract class AccessibleAbstractButton
  1289.         extends AccessibleJComponent implements AccessibleAction, 
  1290.         AccessibleValue {
  1291.  
  1292.         /**
  1293.          * Get the accessible name of this object.  
  1294.          *
  1295.          * @return the localized name of the object -- can be null if this 
  1296.          * object does not have a name
  1297.          */
  1298.         public String getAccessibleName() {
  1299.             if (accessibleName != null) {
  1300.                 return accessibleName;
  1301.             } else {
  1302.                 if (getText() == null) {
  1303.                     return super.getAccessibleName();
  1304.                 } else {
  1305.                     return getText();
  1306.                 }
  1307.             }
  1308.         }
  1309.  
  1310.         /**
  1311.          * Get the state set of this object.
  1312.          *
  1313.          * @return an instance of AccessibleState containing the current state 
  1314.          * of the object
  1315.          * @see AccessibleState
  1316.          */
  1317.         public AccessibleStateSet getAccessibleStateSet() {
  1318.         AccessibleStateSet states = super.getAccessibleStateSet();
  1319.             if (getModel().isArmed()) {
  1320.                 states.add(AccessibleState.ARMED);
  1321.             }
  1322.             if (hasFocus()) {
  1323.                 states.add(AccessibleState.FOCUSED);
  1324.             }
  1325.             if (getModel().isPressed()) {
  1326.                 states.add(AccessibleState.PRESSED);
  1327.             }
  1328.             if (isSelected()) {
  1329.                 states.add(AccessibleState.CHECKED);
  1330.             }
  1331.             return states;
  1332.         }
  1333.  
  1334.         /**
  1335.          * Get the AccessibleAction associated with this object if one
  1336.          * exists.  Otherwise return null.
  1337.          */
  1338.         public AccessibleAction getAccessibleAction() {
  1339.             return this;
  1340.         }
  1341.  
  1342.         /**
  1343.          * Get the AccessibleValue associated with this object if one
  1344.          * exists.  Otherwise return null.
  1345.          */
  1346.         public AccessibleValue getAccessibleValue() {
  1347.             return this;
  1348.         }
  1349.  
  1350.         /**
  1351.          * Returns the number of Actions available in this object.
  1352.          * If there is more than one, the first one is the "default"
  1353.          * action.
  1354.          *
  1355.          * @return the number of Actions in this object
  1356.          */
  1357.         public int getAccessibleActionCount() {
  1358.             return 1;
  1359.         }
  1360.     
  1361.         /**
  1362.          * Return a description of the specified action of the object.
  1363.          *
  1364.          * @param i zero-based index of the actions
  1365.          */
  1366.         public String getAccessibleActionDescription(int i) {
  1367.             if (i == 0) {
  1368.                 // [[[PENDING:  WDW -- need to provide a localized string]]]
  1369.                 return new String("click");
  1370.             } else {
  1371.                 return null;
  1372.             }
  1373.         }
  1374.     
  1375.         /**
  1376.          * Perform the specified Action on the object
  1377.          *
  1378.          * @param i zero-based index of actions
  1379.          * @return true if the the action was performed; else false.
  1380.          */
  1381.         public boolean doAccessibleAction(int i) {
  1382.             if (i == 0) {
  1383.                 doClick();
  1384.                 return true;
  1385.             } else {
  1386.                 return false;
  1387.             }
  1388.         }
  1389.  
  1390.         /**
  1391.          * Get the value of this object as a Number.
  1392.          *
  1393.          * @return An Integer of 0 if this isn't selected or an Integer of 1 if
  1394.          * this is selected.
  1395.          * @see AbstractButton#isSelected
  1396.          */
  1397.         public Number getCurrentAccessibleValue() {
  1398.             if (isSelected()) {
  1399.                 return new Integer(1);
  1400.             } else {
  1401.                 return new Integer(0);
  1402.             }
  1403.         }
  1404.  
  1405.         /**
  1406.          * Set the value of this object as a Number.
  1407.          *
  1408.          * @return True if the value was set.
  1409.          */
  1410.         public boolean setCurrentAccessibleValue(Number n) {
  1411.             if (n instanceof Integer) {
  1412.                 int i = n.intValue();
  1413.                 if (i == 0) {
  1414.                     setSelected(false);
  1415.                 } else {
  1416.                     setSelected(true);
  1417.                 }
  1418.                 return true;
  1419.             } else {
  1420.                 return false;
  1421.             }
  1422.         }
  1423.  
  1424.         /**
  1425.          * Get the minimum value of this object as a Number.
  1426.          *
  1427.          * @return An Integer of 0.
  1428.          */
  1429.         public Number getMinimumAccessibleValue() {
  1430.             return new Integer(0);
  1431.         }
  1432.  
  1433.         /**
  1434.          * Get the maximum value of this object as a Number.
  1435.          *
  1436.          * @return An Integer of 1.
  1437.          */
  1438.         public Number getMaximumAccessibleValue() {
  1439.             return new Integer(1);
  1440.         }
  1441.     }
  1442. }
  1443.